package controller;

import com.artofsolving.jodconverter.DocumentConverter;
import com.artofsolving.jodconverter.openoffice.connection.OpenOfficeConnection;
import com.artofsolving.jodconverter.openoffice.connection.SocketOpenOfficeConnection;
import com.artofsolving.jodconverter.openoffice.converter.StreamOpenOfficeDocumentConverter;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.multipart.MultipartFile;
import util.PropertiesLoader;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;

@Controller
@RequestMapping("/file")
public class FileController {
    //文件共享
    @RequestMapping("/sharefiles")
    public String sharefiles(Model model,HttpSession httpSession){
        String username=(String)httpSession.getAttribute("username");
        if(username!=null&&!username.equals("")) {
            List<Map<String, Object>> filelist=getFiles(getUploadDirect());
            model.addAttribute("filelist", filelist);
            return "sharefiles";
        }else{
            return "fail";
        }
    }
    /**
     * @Author：
     * @Description：获取某个目录下所有直接下级文件，不包括目录下的子目录的下的文件，所以不用递归获取
     * @Date：
     */
    public static List<Map<String, Object>> getFiles(String path) {
        //List<String> files = new ArrayList<String>();
        List<Map<String, Object>> files = new ArrayList<Map<String, Object>>();
        File file = new File(path);
        File[] tempList = file.listFiles();

        Arrays.sort(tempList, new Comparator<File>() {
            public int compare(File f1, File f2) {
                long diff = f2.lastModified()-f1.lastModified() ;
                if (diff > 0)
                    return 1;
                else if (diff == 0)
                    return 0;
                else
                    return -1;
            }

            public boolean equals(Object obj) {
                return true;
            }

        });

        for (int i = 0; i < tempList.length; i++) {
            if (tempList[i].isFile()) {
                Map<String, Object> m3 = new HashMap<String, Object>();
                String fullname=tempList[i].getName();
                m3.put("fullname",fullname);
                String filename=fullname.substring(fullname.indexOf("-")+1);
                m3.put("filename",filename);
                String uname=fullname.substring(0,fullname.indexOf("-")<0?0:fullname.indexOf("-"));
                m3.put("username",uname);
                m3.put("path",tempList[i].getPath());
                Date filetime = new Date(tempList[i].lastModified());
                SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                String dateString = formatter.format(filetime);
                m3.put("mdate",dateString);
                files.add(m3);
                //文件名，不包含路径
                //String fileName = tempList[i].getName();
            }
            if (tempList[i].isDirectory()) {
                //这里就不递归了，
            }
        }
        return files;
    }

    //SpringMVC中使用  MultipartFile file对象接受上传文件,必须保证 后台参数的名称和表单提交的文件的名称一致
    @RequestMapping("/upload")
    public String singleUpload(MultipartFile file) throws IOException {
        if(null!=file && file.getSize()>0){
            System.out.println(file.getName());//获取上传文件的表单名称
            System.out.println(file.getContentType());//MIME类型
            System.out.println(file.getSize());//文件大小
            System.out.println(file.getOriginalFilename());//获取上传文件的完整名称

            Subject currentUser = SecurityUtils.getSubject();
            Session session = currentUser.getSession();
            String sessionusername = (String) session.getAttribute("username");
            //获取上传文件对应的输入流
            //InputStream in = headImg.getInputStream();
            //创建一个磁盘目录用于保存文件
            File destFile = new File(getUploadDirect());
            if (!destFile.exists()) {
                destFile.mkdir();
            }
            //使用uuid作为文件随机名称
            String fileName = file.getOriginalFilename();//UUID.randomUUID().toString().replaceAll("-", "");
            //使用FileNameUtils获取上传文件名的后缀
            String extension = FilenameUtils.getExtension(file.getOriginalFilename());// jpg , png 等等
            //创建新的文件名称
            String newFileName = sessionusername + "-" + fileName;

            //创建要保存文件的File对象
            File savefile = new File(destFile, newFileName);
            //保存文件到本地磁盘
            file.transferTo(savefile);
        }
        return "redirect:/file/sharefiles";
    }

    /*
     * 下载文件思路
     * 1. 接受需要下载文件名称，根据文件名称，找到磁盘对应的文件，读取到内存中形成一个输入流
     * 2. 将输入流通过响应对象（HttpServletResponse）响应给浏览器（下载）
     *
     * 注意：Web一般只会下载小型文件
     *
     */
    @RequestMapping("/download")
    public void upload(String fileName, HttpServletResponse response) throws IOException {
        //0. 判断是否vip，有积分，金豆
        //1. 接受文件名，读取磁盘对应的文件，创建输入流对象
        FileInputStream inputStream = new FileInputStream(getUploadDirect() + "\\" + fileName);
        //2.获取响应对象的输出流
        ServletOutputStream outputStream = response.getOutputStream();
        //3.文件下载文件名的编码使用ISO-08859-1编码
        //我们需要将我们UTF-8的 filename转换ISO-8859-1编码
        //3.1先将字符串以UTF-8转换成字节数组
        byte[] bytes = fileName.getBytes("UTF-8");
        //3.2再将字节数组以 ISO-8859-1转换字符串
        fileName = new String(bytes, "ISO-8859-1");
        //4.响应的内容应该是以附件的形式响应给浏览器(设置响应头)
        response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
        //5.响应文件给浏览器
        IOUtils.copy(inputStream, outputStream);
    }

    @RequestMapping("/delefile")
    public void delefile(String fileName, HttpServletResponse response) throws IOException {
        File destFile = new File(getUploadDirect()+ "\\" + fileName);
        if(destFile.exists()){
            destFile.delete();
        }
        //return "redirect:/sharefiles";
    }

    //文件预览
    @RequestMapping("/view")
    public String viewofficetopdfFile(String filename, HttpServletRequest request, HttpServletResponse response, Model model) throws Exception {
        if (null!=filename && !"".equals(filename)) {
            File filetemp=new File(getUploadDirect()+ "\\temp\\");
            if(!filetemp.exists()){//如果文件夹不存在
                filetemp.mkdir();//创建文件夹
            }
            // 目标文件路径
            String fileName=filename;
            String filePath =getUploadDirect()+ "\\"+filename;
            String filePath_pdf =getUploadDirect()+ "\\temp\\"+filename;
            /* 1)根据项目所在的服务器环境,确定路径中的 / 和 \ */
			/*String osName = System.getProperty("os.name");
			if (Pattern.matches("Linux.*", osName)) {
				filePath = "/" + filePath.replace("\\", "/");
			} else if (Pattern.matches("Windows.*", osName)) {
				filePath.replace("/", "\\");
			}*/
            /* 2)获得文件名后缀 */
            filePath=filePath.replace("//", "/");
            String ext = "";
            if (!"".equals(fileName) && fileName.contains(".")) {
                ext = fileName.substring(fileName.lastIndexOf(".") + 1,
                        fileName.length()).toUpperCase();
            }
            /* 3)根据文件类型不同进行预览 */
            /* 预览图片 */
            if ("PNG".equals(ext) || "JPEG".equals(ext) || "JPG".equals(ext)) {
                model.addAttribute("filetype", "image");
                model.addAttribute("fileurl", fileName);
            }
            else if ("BMP".equals(ext)||"GIF".equals(ext)) {
                model.addAttribute("filetype", "image");
                model.addAttribute("fileurl", fileName);
            }else if ("PDF".equals(ext)) {
                model.addAttribute("filetype", "office");
                model.addAttribute("fileurl", fileName);
            }else if ("MP4".equals(ext)||"wmv".equals(ext)||"flv".equals(ext)||"avi".equals(ext)||"m4v".equals(ext)||"ogv".equals(ext)) {
                model.addAttribute("filetype", "video");
                model.addAttribute("fileurl", fileName);
            }else if ("DOC".equals(ext) || "DOCX".equals(ext) || "XLS".equals(ext)
                    || "XLSX".equals(ext) || "PPT".equals(ext)
                    || "PPTX".equals(ext)) {
                File docFile = new File(filePath);
                File pdfFile=new File(filePath_pdf.substring(0,filePath_pdf.lastIndexOf("."))+".pdf");
                /* 判断即将要转换的文件是否真实存在 */
                if (docFile.exists()) {
                    /* 判断改文件是否已经被转换过,若已经转换则直接预览 */
                    if (!pdfFile.exists()) {
                        /* 打开OpenOffice连接, */
                        OpenOfficeConnection connection = new SocketOpenOfficeConnection(getPropertie("offict.pdf.server"),Integer.parseInt(getPropertie("offict.pdf.port")));
                        try {
                            connection.connect();
                            //DocumentConverter converter = new OpenOfficeDocumentConverter(connection);
                            DocumentConverter converter = new StreamOpenOfficeDocumentConverter(connection);
                            converter.convert(docFile, pdfFile);
                            connection.disconnect();
                            //filePath = file.getPath();
                        } catch (java.net.ConnectException e) {
                            e.printStackTrace(); // openoffice 服务未启动
                            throw e;
                        } catch (com.artofsolving.jodconverter.openoffice.connection.OpenOfficeException e) {
                            e.printStackTrace(); // 读取转换文件失败
                            throw e;
                        } catch (Exception e) {
                            e.printStackTrace();
                            throw e;
                        } finally { // 发生exception时, connection不会自动切断, 程序会一直挂着
                            try {
                                if (connection != null) {
                                    connection.disconnect();
                                    connection = null;
                                }
                            } catch (Exception e) {}
                        }
                    } else {
                        //filePath = file.getPath(); // 文件已经转换过
                        //response.setContentType("application/pdf");
                    }
                    model.addAttribute("filetype", "office");
                    model.addAttribute("fileurl", fileName.substring(0,fileName.lastIndexOf("."))+".pdf");
                }else{
                    //"需要预览的文档在服务器中不存在!";
                    model.addAttribute("filetype", "error");
                    model.addAttribute("fileurl", "");
                }
            }else{
                model.addAttribute("filetype", "error");
                model.addAttribute("fileurl", "");
            }
            /* 将文件写入输出流,显示在界面上,实现预览效果 */
			/*FileInputStream fis = new FileInputStream(filePath);
			OutputStream os = response.getOutputStream();
			try {
				int count = 0;
				byte[] buffer = new byte[1024 * 1024];
				while ((count = fis.read(buffer)) != -1)
					os.write(buffer, 0, count);
				os.flush();
			} catch (IOException e) {
				e.printStackTrace();
			} finally {
				if (os != null)
					os.close();
				if (fis != null)
					fis.close();
			}*/
        }else{
            model.addAttribute("filetype", "");
            model.addAttribute("fileurl", "");
        }
        return "pdf_view";
    }
    @RequestMapping("/viewforce")
    public String viewofficetopdfFilePdf(String file,Model model){
        model.addAttribute("file", file);
        //return "pdf_viewforce";
        //return "forward:/pdf_viewforce";
        return "pdf_viewforce";
    }

    public String getUploadDirect() {
        PropertiesLoader appconfig = new PropertiesLoader("conf/application.properties");
        String UploadDirect = appconfig.getProperty("upload.files.base.path");
        return UploadDirect;
    }

    public String getPropertie(String PropertienKey) {
        PropertiesLoader appconfig = new PropertiesLoader("conf/application.properties");
        String ps = appconfig.getProperty(PropertienKey);
        return ps;
    }

    @RequestMapping(value = "/downLoadio", method = RequestMethod.GET)
    public ResponseEntity<byte[]> pdfDownload(String filename,HttpServletRequest httpServletRequest) throws Exception {
        //String tempPath = path;
        String downloadPath = getUploadDirect()+ "\\temp\\" + filename;
        File file = new File(downloadPath);
        if(!file.exists()){
            file = new File(getUploadDirect()+ "\\" + filename);
        }
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setContentType(MediaType.parseMediaType("application/pdf"));
        //httpHeaders.setContentDispositionFormData("attachment", java.net.URLEncoder.encode(fileName,"UTF-8"));
        return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file), httpHeaders, HttpStatus.OK);
    }
}
